package com.cz.mybatis.ss;

/**
 * @description TODO
 * @auther chengzhen
 * @date 2021/9/17 19:37
 * Debug the code, debug the world!
 */

import java.util.*;

/**
 * 有n名开发人员，m个任务待分配。skills[i]表示第i人员的能力值，tasks[i]表示第i个任务的工作量。
 * 开发同一时间只能处理一项任务，第i项任务最早第i天可以开始处理，处理第i项任务时，需要为他分配一名能力值最大的空闲人员，
 * 相同则选下标最小的。如果第t天分配了第j项任务，t+tasks[j]，恢复空闲。
 * 没有空闲人员等待，多项分配，下标最小。多空多分
 * 返回长度为m的任务分配方案数组assigns,其中assigns[i]为第i项任务分配的开发人员下标
 *
 * [4,4,7]  [1, 2, 3, 2, 1, 2]
 *
 * [2, 2, 0, 2, 1, 2]
 */

public class WangYi {

    public static void main(String[] args) {
        int[] skills = new int[]{4, 4, 7};
        int[] tasks = new int[]{1, 2, 3, 2, 1, 2};
        System.out.println(Arrays.toString(solution(skills, tasks)));
    }

    static HashMap<Integer, Boolean> personFree = new HashMap<>(); //前面是人员下标，后面是是否空闲
    static HashMap<Integer, Integer> personDaysFree = new HashMap<>(); //前面是人员下标，后面是到天数空闲
    static TreeMap<Integer, Integer> personIndexSkills = new TreeMap<>(new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1 - o2;
        }
    });

    public static Integer[] solution(int[] skills, int[] tasks){
        List<Integer> personExecuteTaskIndex = new ArrayList<>();
        for(int i = 0; i < skills.length; i  ++){
            personFree.put(i, true);
        }
        for(int i = 0; i < skills.length; i ++){
            personIndexSkills.put(i, skills[i]);
        }
        int freeMaxSKillIndex = -1;
        int taskIndex = 0;
        int days = 0;
        while (taskIndex != tasks.length) {
            //检查哪些人到 days 天空闲
            freeMaxSKillIndex = getMaxFreeSkillIndex();
            //把taskIndex 分给 freeMaxSKillIndex, 如果分成功了则执行以下
            if(freeMaxSKillIndex != -1 && days >= taskIndex){
                personExecuteTaskIndex.add(freeMaxSKillIndex);
                personFree.put(freeMaxSKillIndex, false);
                personDaysFree.put(freeMaxSKillIndex, days + tasks[taskIndex]);
                taskIndex++;
            }
            days++;
            checkPersonFreeAtDays(days);
        }
        return personExecuteTaskIndex.toArray(new Integer[skills.length]);
    }

    //到days 天检查人员是否空闲
    public static void checkPersonFreeAtDays(Integer days){
        personDaysFree.entrySet().forEach(o->{
            if(o.getValue() == days){
                personFree.put(o.getKey(), true);
            }
        });
        personFree.entrySet().forEach(o1->{
            if(personFree.get(o1.getKey())){
                personDaysFree.remove(o1.getKey());
            }
        });
    }

    //获取空闲的 能力值最大人员的 下标，没有则返回-1
    public static int getMaxFreeSkillIndex(){
        int max = -1;
        int index = -1;
        for (Map.Entry<Integer, Integer> o : personIndexSkills.entrySet()) {
            if (personFree.get(o.getKey()) && (o.getValue() > max)) {
                max = o.getValue();
                index = o.getKey();
            }
        }
        return index;
    }



}
